home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
asm
/
alib11b.zip
/
CODE1.ZIP
/
DISKINFO
/
MAKETEMP.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-01-05
|
12KB
|
404 lines
;****************************************************************
; Create Temporary File with a Unique Name.
; Copyright (c) 1993 FM de Monasterio. All Rights Reserved.
;
; These procedures may be distributed freely and used in
; application programs with acknowledgement, but may not
; be sold in unit form.
;
; Written for OPTASM 1.65
;----------------------------------------------------------------
; Input:
; DS:DX -> ASCIIz backslash-ending path (e.g."D:\TMP\DATA\",0)
; CX = Attributes: 0=Normal, 1=ReadOnly, 2=Hidden, 4=System
; 20h=Archive, or their ORed combinations
; Output:
; Success: CF=0, AX=handle, 13-byte TempFile field at end
; Failure: CF=1, AX=error code: 03h=Path not found
; 04h=Too many open files
; 05h=Access denied
; 50h=Unique name not found
; ??h=Disk critical error code
; Alters: AX, Flags (DF=0)
;****************************************************************
_CODE segment para public '_code'
assume cs:_code, ds:nothing, es:nothing
PUBLIC TempFile
; LOCAL DATA - Even alignment of words and strings
EVEN
Int24Vect LABEL DWORD
Int24Offs DW ? ; old INT 24h address
Int24Segm DW ?
TempAddr LABEL DWORD ; address of name field
TempOffs DW ? ; in caller's DS segment
TempSegm DW ?
; Temporary ASCIIz filepath
TempBuff DB 120 dup (?) ; TempPath buffer
TempName DB 8 dup (?) ; 8-character name
DB 0 ; ASCIIz mark
TempDisk DB 0 ; TempPath drive
TempAttr DW ? ; file attribute mask
TempTail DW ? ; path-end pointer storage
TempDate DW ? ; date stamp
TempTime DW ? ; time stamp
Int24Flag DB 0 ; 0=no error, 1=crit error
;----------------------------------------------------------------
EVEN
TempFile PROC FAR
push ES ; save used registers
push DS
push DI
push SI
push DX
push BX
push CX
mov SI,DX ; save TempPath offset
; Check DOS version to decide whether to use function 5Ah
; (MS-DOS 3.x through 4.x) or 5Bh (MS-DOS 5A/B and 6A).
;
; Use first function 3306h (get 'true' MS-DOS version) to
; exclude MS-DOS 5+ is executing under SETVER (or another
; TSR) asserting a different version via fxn 30h:
;
; BH= Minor, BL= Major version
; DL= (bits 0-2) Revision no. (Microsoft uses "A"=0, "B"=1)
; CF= Clear in Revision 5A, set in Revision 5B
; DH= Memory location flag bit 3=1: DOS in ROM, else in RAM
; flag bit 4=1: DOS in HMA, else in 640K
xor BX,BX ; MS-DOS 5+ changes BX/DX
mov AX,3306h ; fxn get true MS-DOS ver
int 21h
; Because MS-DOS 5B sets CY, the CF status cannot be used to
; exclude DR-DOS 5+, which also sets CY upon fxn 3306h. Use
; instead BX, which is modified by MS-DOS 5+ (but not by MS-
; or PC-DOS 3 through 4, or by DR-DOS 5 or 6).
;
cmp BX,5 ; MS-DOS 5?
je TempDosBug ; yes, use fxn 5Bh
; Next comp assumes MS-DOS 6 is still buggy - Delete, if not
cmp BX,6 ; assume MS-DOS 6 is
je TempDosBug ; also buggy but that
; a future DOS 7+ is not
;
; Execute function 5Ah and return
;
TempDosOk: mov AH,5Ah ; fxn create temp file
mov DX,SI ; CX and DS unchanged
int 21h
jmp TempFileRetf ; pop and return (CF safe)
;
; ** Function 5Ah buggy - Implement alternative procedure **
;
EVEN
TempDosBug: cld ; strings forward
push CS
pop ES
assume es:_code
mov es:[TempAttr],CX ; save attribute mask
mov es:[TempSegm],DS ; and filepath segment
; (SI has path offset)
;
; Copy TempPath to local buffer
;
mov DI,offset TempBuff ; ES:DI -> local buffer
mov AX,ds:[SI] ; DS:SI -> TempPath
mov CX,120 ; maximum buffer length
cmp AH,":" ; drive spec given?
jne TempPathByte ; no, skip
mov es:[TempDisk],AL ; else update INT-24h ISR
EVEN
TempPathByte: lodsb ; get TempPath character
or AL,AL ; reached null marker?
jz TempPathNull ; yes, skip over
stosb ; else save in buffer and
loop TempPathByte ; get next if within bounds
stc ; too long, signal error and
mov AX,3 ; return Path_Not_Found code
jmp TempFileRetf
;
; Found end of ASCIIz path - Save pointers
EVEN ;
TempPathNull: mov DX,CS
mov DS,DX ; restore DS addressability
assume ds:_code
dec SI ; adjust ptr to last byte
mov [TempTail],DI ; save local tail pointer
mov [TempOffs],SI ; offset for appending name
;
; Save and hook Critical Error handler ** PRESERVE DX=CS **
;
mov AX,3524h ; fxn get INT 24h vector
int 21h
mov [Int24Offs],BX ; offset
mov [Int24Segm],ES ; segment
mov ES,DX
assume es:_code
mov AX,2524h ; fxn set INT 24h vector
mov DX,offset Int24Temp ; ES:DX -> new handler
int 21h
;
; == Reentry point: Calculate new time/date stamp ==
EVEN ;
TempFileName: call GetDate ; AX=(((Y-1980)*512)+M*32)+D
mov [TempDate],AX ; store packed date
call GetTime ; AX=((h*4096)+m*64)+s
mov BX,32 ; init bit rotation counter
; * PRESERVE BX UNTIL DONE *
;
; == Reentry point: Old stamp rotation loop ==
EVEN ;
TempFileLoop: mov DI,offset TempName ; ES:DI -> name chars 1-4
mov [TempTime],AX ; store packed time
call Word2Hex ; write first half stamp
mov DI,offset TempName[4] ; ES:DI -> name chars 5-8
mov AX,[TempDate] ; read packed date
call Word2Hex ; write second half stamp
;
; Append tentative filename to TempPath string
;
mov SI,offset TempName ; DS:SI -> start of name
mov DI,[TempTail] ; ES:DI -> end of path
mov CX,4 ; name to append (words)
rep movsw
;
; Attempt to create new file with current name
;
mov AH,5Bh ; fxn create new file
mov CX,[TempAttr] ; attribute mask
mov DX,offset TempBuff ; DS:DX -> "unique" name
int 21h
mov DX,AX ; save handle/error code
jc TempFileFail ; CF=1, DOS error in AX
mov AL,[Int24Flag] ; get critical-flag status
or AL,AL ; error? (ORing sets CF=0)
jz TempFileExit ; no, return success
TempFileQuit: push DX ; save error code in stack
stc ; reset CF to signal error
jmp short TempFileCrit
;
; *** File creation error
EVEN ;
TempFileFail: cmp AX,50h ; File_Exists error code?
jne TempFileQuit ; no, return failure
dec BX ; all 32 bits rotated?
jz TempFileName ; yes, make new stamp
;
; 32-bit ROL date/time stamp by 1 bit
;
mov DX,[TempDate]
mov AX,[TempTime] ; get old date:time dword
shl DX,1 ; 0-> DX b0... DX b15-> CF
rcl AX,1 ; CF-> AX b0... AX b15-> CF
adc DX,0 ; CF-> DX b0
mov [TempDate],DX ; store rotated date
jmp short TempFileLoop ; and try again
;
; *** Successful temporary file creation:
; Return the 8-character unique name
EVEN ;
TempFileExit: push DX ; save file handle
mov CX,4 ; name to append (words)
mov SI,offset TempName ; DS:SI -> unique name
les DI,[TempAddr] ; ES:DI -> caller's field
rep movsw
;
; Restore INT-24h vector
;
TempFileCrit: pushf ; save CF status
mov AX,2524h ; fxn set INT 24h vector
lds DX,[Int24Vect] ; to old address in DS:DX
int 21h
popf ; restore CF and get back
pop AX ; the handle or error code
;
; Restore registers and return to caller
;
TempFileRetf: pop CX ; and restore registers
pop BX
pop DX
pop SI
pop DI
pop DS
pop ES
retf ; far return to caller
TempFile ENDP
;****************************************************************
; Local INT-24h Handler (DOS critical error)
; On entry:
; AH : bit 7 = 0 if disk I/O error
; DI : lower byte = error code (upper byte undefined)
; BP:SI-> device header structure containing info about
; the device on which the error took place.
; On exit:
; AL = value specifying action that DOS should take
; depending on what is allowed (AH bits 5-3).
;****************************************************************
assume ds:nothing
EVEN
Int24Temp PROC FAR
test AH,80h ; disk error?
jnz Int24Exit ; no, exit
cmp cs:[TempDisk],0 ; drive letter specified?
je Int24Disk ; no, assume TempPath disk
add AL,"A" ; get 0=A, 1=B, etc
cmp AL,cs:[TempDisk] ; is this the right drive?
je Int24Disk ; yes, handle error
sub AL,"A" ; else let DOS handle it
Int24Exit: jmp cs:[Int24Vect]
;
; Drive error
EVEN ;
Int24Disk: mov AX,DI ; save critical error code
mov cs:[Int24Flag],AL ; from lower byte of DI
xor AX,AX ; and tell DOS to ignore
iret ; error (or terminate fxn)
Int24Temp ENDP
;****************************************************************
; Pack date in DOS-file stamp format
; bit 09-15: Year (0-119 offset from 1980) * 512
; bit 05-08: Month (1-12) * 32
; bit 00-04: Day (1-31)
;
; Input: None
; Output: AX = [([Year-1980]*512)+Month*32]+Day
; Alters: AX BX CX DX
;****************************************************************
assume ds:_code
EVEN
GetDate PROC NEAR
mov AH,2Ah ; fxn get current date
int 21h ; CX=YY, DH=MM, DL=DD
mov AX,CX ; get AX=1980 through 2099
sub AX,1980 ; and make offset from 1980
mov CL,1 ; shift reps for (YY*256)*2
jmp short GetStamp ; and chain into next proc
GetDate ENDP
;****************************************************************
; Pack time in quasi-DOS-file format
; bits 12-15: hours (0-12) * 4096
; bits 06-10: minutes (0-59) * 64
; bits 00-05: seconds (0-59)
;
; instead of DOS format
; bit 11-15: hours (0-23) * 2048
; bit 05-10: minutes (0-59) * 32
; bit 00-04: seconds (0-29) in 2-second intervals
;
; Input: None
; Output: AX = [(Hour*4096)+Minute*64]+Second
; Alters: AX BX CX DX
;****************************************************************
assume ds:_code
EVEN
GetTime PROC NEAR
mov AH,2Ch ; fxn get current time
int 21h ; CH=hh, CL=mm, DH=ss
mov AL,CH ; copy 0-23 hour
sub AL,12 ; AM or PM?
jnc GetHour ; PM, keep difference
mov AL,CH ; else AM
EVEN
GetHour: cbw ; AX = 0-12 h
mov DL,DH ; DL = 0-59 s
mov DH,CL ; DH = 0-59 m
shl DH,1 ; DH = m*2
mov CL,4 ; shift reps for (h*256)*16
;
; Repack data in stamp format
EVEN ;
GetStamp: xchg AH,AL ; fast Y*256 or h*256
shl AX,CL ; (Y-1980)*512 or h*4096
xor BX,BX ; zero register
xchg BL,DH ; DX = D or s, BX=M or m*2)
mov CL,5 ; get times-32 shift reps
shl BX,CL ; BX = M*32 or m*64
add AX,BX
add AX,DX ; AX=(h*4096)+(m*64)+s or
retn ; AX=(Y-1980)*512+M*32+D
GetTime ENDP
;****************************************************************
; Convert 16-bit binary to 4-ASCII hexadecimals and store as ES:DI
;
; Input: AX = binary number (word), ES:DI -> memory offset
; Output: None
; Alters: AX CX DX DI
;****************************************************************
assume ds:_code, es:_code
EVEN
Word2Hex PROC NEAR
std ; set to fill backwards
add DI,3 ; (3+1) digits to fill
mov CX,4 ; in 4 nibbles
;
; ** PRESERVE [BX] **
EVEN ;
Word2Hex1: mov DX,AX ; save accumulator
and AX,000Fh ; read LSN
cmp AL,9 ; 0Ah-0Fh range?
ja Word2Hex2 ; yes
add AL,"0" ; no, make ASCII digit
jmp short Word2Hex3 ; and store it
Word2Hex2: add AL,55 ; else make ASCII letter
Word2Hex3: stosb ; and store it
mov AX,DX
ror AX,1 ; rotate nibble
ror AX,1 ; ** PRESERVE [CX] **
ror AX,1
ror AX,1
loop Word2Hex1 ; convert next nibble
cld ; clear DF
retn
Word2Hex ENDP
_CODE ends
END